package momo.app.comms;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

import momo.app.comms.CommsHistory;
import momo.app.config.AppConfig;
import momo.app.status.StatusManager;
import momo.app.structure.Message;
import momo.app.structure.SessionController;
import momo.app.structure.SessionTracker;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


public class StateResetter
{
	private Log log = LogFactory.getLog(StateResetter.class);
	static private StateResetter resetter;
	private ScheduledExecutorService scheduler;
	private AtomicBoolean hasTask;
	
	private StateResetter()
	{
		scheduler = Executors.newScheduledThreadPool(1);
		hasTask = new AtomicBoolean(false);
	}
	
	static public StateResetter getInstance()
	{
		if ( resetter == null )
			resetter = new StateResetter();
		return resetter;
	}
	
	synchronized public void reset(int newSID, boolean isInitiator)
	{
		SessionTracker tracker = SessionTracker.getInstance();
		
		if ( isInitiator )
			newSID = tracker.getGeneratedSID();
		
		if ( hasTask.compareAndSet(false, true) )
		{
			tracker.setSID(newSID);
			
			if ( isInitiator )
				broadcastNewSID(newSID);
			
			scheduler.schedule(
					new Runnable()
					{
						public void run()
						{
							int newSID = SessionTracker.getInstance().getSID();
							CommsHistory.getInstance().reset();
							SessionController.getInstance().setSessionId( newSID );
							hasTask.compareAndSet(true, false);
							if ( log.isDebugEnabled() )
								log.debug("Session Id has changed to: " + newSID );
						}
					},
					10,
					TimeUnit.SECONDS);
		}else
		{
			boolean isNewSID = tracker.compareAndSet(newSID);
			if ( isNewSID && isInitiator )
			{
				//broadcast iff newSID is bigger and is initiated by me
				broadcastNewSID(newSID);
			}
		}
	}
	
	synchronized public boolean hasTask()
	{
		return hasTask.get();
	}
	
	private void broadcastNewSID(int newSID)
	{
		StatusManager.getInstance().broadcast(
				new Message(
						Message.BROADCAST, 
						AppConfig.getInstance().getId(), 
						Message.RESET_STATE, 
						""+newSID));
	}
	
}//end of class StateReseter
